package com.sunlands.zlcx.usercenter.service.status;

import com.sunlands.zlcx.usercenter.client.SocketService;
import com.sunlands.zlcx.usercenter.client.bean.ShareMsgParamVO;
import com.sunlands.zlcx.usercenter.config.RedisConfig;
import com.sunlands.zlcx.usercenter.constant.LearningStatus;
import com.sunlands.zlcx.usercenter.constant.RedisKeyConst;
import com.sunlands.zlcx.usercenter.domain.UsersTargetRelationDO;
import com.sunlands.zlcx.usercenter.exception.UserNotLearningException;
import com.sunlands.zlcx.usercenter.service.status.common.AbstractStudyStatus;
import com.sunlands.zlcx.usercenter.util.AssertUtil;
import com.sunlands.zlcx.usercenter.vo.UsersStudyInfoVO;
import com.sunlands.zlcx.usercenter.vo.UsersVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.sunlands.zlcx.usercenter.config.RedisConfig.CacheKeys.USERS_BY_ID;
import static com.sunlands.zlcx.usercenter.config.RedisConfig.CacheKeys.USER_TARGET_BY_USERID;
import static com.sunlands.zlcx.usercenter.constant.MessageType.TIME_LEARN_ROOM_SIT_UP_NOTICE;

/**
 * @author gaoyanfeng
 * @create 2019-04-26 18:07
 **/
@Component
@Slf4j
public class OrdernaryCountTime extends AbstractStudyStatus {

    @Autowired
    private SocketService socketService;
    @Resource(name = "commonTaskExecutor")
    private AsyncTaskExecutor commonTaskExecutor;

    @Override
    @Caching(evict = {
            @CacheEvict(cacheNames = USER_TARGET_BY_USERID, key = "#usersStudyInfoVO.userId", condition = "#usersStudyInfoVO.userId != null"),
    })
    public void handle(UsersStudyInfoVO usersStudyInfoVO, UsersTargetRelationDO usersTargetRelationDO) {
        Long userId = usersTargetRelationDO.getUserId();
        usersStudyInfoVO.setEndTime(new Date());
        UsersVO usersVO = usersService.findOne(userId);
        LearningStatus learningStatus = LearningStatus.getLearningStatus(usersVO.getStatus());
        if (learningStatus != LearningStatus.LEARN_TIMING && learningStatus != LearningStatus.LEARN_TIMING_PAUSE && learningStatus != LearningStatus.LEARN_TIMING_CONINUE) {
            //用户没有在学习中
            return;
        }
        long endTime = usersStudyInfoVO.getEndTime().getTime();
        long startTime = usersVO.getStartLearnTime().getTime();
        log.info("timeDiff={},learningStatus={}", endTime - startTime, learningStatus);
        if (endTime < startTime) {
            throw new IllegalArgumentException("计时结束时间小于开始时间" + userId);
        }
        Date lastLearningEndTime = usersLearnTimingRepository.getLastLearningEndTime(userId);
        if (null != lastLearningEndTime && endTime < lastLearningEndTime.getTime()) {
            throw new IllegalArgumentException("用户在该时段重复学习" + userId);
        }
        String pauseKey = RedisKeyConst.getPauseLearnTimeByUserid(userId);
        String continueKey = RedisKeyConst.getContinueLearnTimeByUserid(userId);
        List<Date> pauseList = redisTemplate.opsForList().range(pauseKey, 0, -1);
        log.info("OrdernaryCountTime userid={}， pauseList={}", userId, pauseList);
        List<Date> continueList = redisTemplate.opsForList().range(continueKey, 0, -1);
        log.info("OrdernaryCountTime userid={}， continueList={}", userId, continueList);
        long pause = 0L;
        long continu = 0L;
        if (AssertUtil.isNotEmpty(pauseList)) {
            for (Date p : pauseList) {
                pause += p.getTime();
            }
        }
        if (AssertUtil.isNotEmpty(continueList)) {
            for (Date c : continueList) {
                continu += c.getTime();
            }
        }
        long studyTime;
        if (learningStatus == LearningStatus.LEARN_TIMING_PAUSE) {
            studyTime = pause - continu - startTime;
        } else {
            studyTime = endTime + pause - continu - startTime;
        }
        if (studyTime < 0) {
            log.error("学习出现问题userId={},pauseList={}, continueList={}, endTime={}", userId, pauseList, continueList, new Date());
            sendExceptionUtil.sendException("学习出现问题userId" + userId + " pauseList" + pauseList + " continueList=" + continueList + " endTime=" + new Date(), new UserNotLearningException());
            studyTime = 0L;
        }
        usersStudyInfoVO.setStudyMinuteSeconds((int) (studyTime / 1000));
        log.debug("OrdernaryCountTime userid={}， studyTime.intValue()/1000={}", userId, (int) studyTime / 1000);
        redisTemplate.delete(pauseKey);
        redisTemplate.delete(continueKey);
//        redisTemplate.opsForZSet().remove(RedisKeyConst.getUserSetLearnTime(), userId);
        String key = RedisConfig.CacheKeys.USERS_BY_USERNAME + ":" + usersVO.getUsername();
        log.debug("tongzhuo:users:by-username={}", key);
        redisTemplate.delete(key);
        redisTemplate.delete(USERS_BY_ID + ":" + userId);
        learnTimingProcess(usersStudyInfoVO, usersTargetRelationDO, userId);

        commonTaskExecutor.execute(() -> friendMessageNotice(userId));

    }

    private void friendMessageNotice(Long userId) {
        List<UsersVO> onlineFriends = usersService.findOnlineFriend(userId);
        if (onlineFriends.isEmpty()) {
            log.debug("用户专注计时-没有在线的道友和关注他的人，不发送消息 userId = {}", userId);
            return;
        }

        onlineFriends.forEach(friend -> {
            ShareMsgParamVO message = ShareMsgParamVO.builder()
                    .type(TIME_LEARN_ROOM_SIT_UP_NOTICE.getType())
                    .fromUserId(userId.toString())
                    .toId(friend.getId().toString())
                    .realToId(friend.getId())
                    .message("用户结束专注计时")
                    .build();
            log.info("用户专注计时-结束学习： message = {}", message);
            socketService.sendMessage(message);
        });

    }
}
